{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow IO Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# 오디오 데이터 준비 및 증강"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/io/tutorials/audio\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org에서 보기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab에서 실행하기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ko/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub에서소스 보기</a></td>\n",
        "      <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">노트북 다운로드하기</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xHxb-dlhMIzW"
      },
      "source": [
        "## 개요\n",
        "\n",
        "자동 음성 인식의 가장 큰 문제 중 하나는 오디오 데이터를 준비하고 증강시키는 작업입니다. 오디오 데이터 분석에는 시간 또는 주파수 도메인이 포함될 수 있으므로 이미지와 같은 다른 데이터 소스와 비교하여 복잡도가 더욱 높습니다.\n",
        "\n",
        "TensorFlow 에코시스템의 일부인 `tensorflow-io` 패키지는 오디오 데이터의 준비 및 증강을 간편하게 해주는 몇 가지 유용한 오디오 관련 API를 제공합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MUXex9ctTuDB"
      },
      "source": [
        "## 설정"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "upgCc3gXybsA"
      },
      "source": [
        "### 필수 패키지를 설치하고 런타임 다시 시작하기"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uUDYyMZRfkX4"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow-io"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "J0ZKhA6s0Pjp"
      },
      "source": [
        "## 사용법"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yZmI7l_GykcW"
      },
      "source": [
        "### 오디오 파일 읽기\n",
        "\n",
        "TensorFlow IO에서 `tfio.audio.AudioIOTensor` 클래스를 사용하면 오디오 파일을 지연 로드된 `IOTensor`로 읽을 수 있습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "nS3eTBvjt-O5"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_io as tfio\n",
        "\n",
        "audio = tfio.audio.AudioIOTensor('gs://cloud-samples-tests/speech/brooklyn.flac')\n",
        "\n",
        "print(audio)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z9GCyPWNuOm7"
      },
      "source": [
        "위의 예에서 Flac 파일 `brooklyn.flac`는 [Google Cloud](https://cloud.google.com/speech-to-text/docs/quickstart-gcloud)에서 공개적으로 액세스할 수 있는 오디오 클립에서 가져온 것입니다.\n",
        "\n",
        "GCS는 TensorFlow에서 지원되는 파일 시스템이므로 GCS 주소 `gs://cloud-samples-tests/speech/brooklyn.flac`가 직접 사용됩니다. `Flac` 형식 외에 `WAV`, `Ogg`, `MP3` 및 `MP4A`도 자동 파일 형식 감지 기능이 있는 `AudioIOTensor`에서 지원됩니다.\n",
        "\n",
        "`AudioIOTensor`는 지연 로드되므로 처음에는 형상, dtype 및 샘플 속도만 표시됩니다. `AudioIOTensor`의 형상은 `[samples, channels]`로 표시됩니다. 이는 로드한 오디오 클립이 `int16`의 `28979`개 샘플을 갖는 모노 채널임을 의미합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IF_kYz_o2DH4"
      },
      "source": [
        "오디오 클립의 내용은 `to_tensor()`를 통해 또는 슬라이싱을 통해 `AudioIOTensor`를 `Tensor`로 변환하여 필요에 따라서만 판독됩니다. 슬라이싱은 큰 오디오 클립의 일부만 필요한 경우에 특히 유용합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "wtM_ixN724xb"
      },
      "outputs": [],
      "source": [
        "audio_slice = audio[100:]\n",
        "\n",
        "# remove last dimension\n",
        "audio_tensor = tf.squeeze(audio_slice, axis=[-1])\n",
        "\n",
        "print(audio_tensor)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IGnbXuVnSo8T"
      },
      "source": [
        "오디오는 다음을 통해 재생할 수 있습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0rLbVxuFSvVO"
      },
      "outputs": [],
      "source": [
        "from IPython.display import Audio\n",
        "\n",
        "Audio(audio_tensor.numpy(), rate=audio.rate.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fmt4cn304IbG"
      },
      "source": [
        "텐서를 부동 소수점 숫자로 변환하고 오디오 클립을 그래프로 표시하는 것이 더 편리합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZpwajOeR4UMU"
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "\n",
        "tensor = tf.cast(audio_tensor, tf.float32) / 32768.0\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(tensor.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "86qE8BPl5rcA"
      },
      "source": [
        "### 노이즈 제거\n",
        "\n",
        "때로는 오디오에서 노이즈를 제거하는 것이 합리적이며 이때 API `tfio.experimental.audio.trim`을 사용할 수 있습니다. API에서 세그먼트의 `[start, stop]` 위치 쌍이 반환됩니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "eEa0Z5U26Ep3"
      },
      "outputs": [],
      "source": [
        "position = tfio.experimental.audio.trim(tensor, axis=0, epsilon=0.1)\n",
        "print(position)\n",
        "\n",
        "start = position[0]\n",
        "stop = position[1]\n",
        "print(start, stop)\n",
        "\n",
        "processed = tensor[start:stop]\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(processed.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ineBzDeu-lTh"
      },
      "source": [
        "### 페이드 인 및 페이드 아웃\n",
        "\n",
        "유용한 오디오 엔지니어링 기술 중 하나는 오디오 신호를 점차적으로 늘리거나 줄이는 페이딩 기술입니다. 이 기술은 `tfio.experimental.audio.fade`를 통해 수행할 수 있습니다. `tfio.experimental.audio.fade`는 `linear` , `logarithmic` 또는 `exponential`과 같은 다양한 형상의 페이드를 지원합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LfZo0XaaAaeM"
      },
      "outputs": [],
      "source": [
        "fade = tfio.experimental.audio.fade(\n",
        "    processed, fade_in=1000, fade_out=2000, mode=\"logarithmic\")\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(fade.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7rhLvOSZB0k0"
      },
      "source": [
        "### 스펙트럼 사진\n",
        "\n",
        "고급 오디오 처리는 종종 시간 경과에 따른 주파수 변화에 적용됩니다. `tensorflow-io`에서 파형은 `tfio.experimental.audio.spectrogram`을 통해 스펙트럼 사진으로 변환할 수 있습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UyFMBK-LDDnN"
      },
      "outputs": [],
      "source": [
        "# Convert to spectrogram\n",
        "spectrogram = tfio.experimental.audio.spectrogram(\n",
        "    fade, nfft=512, window=512, stride=256)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(tf.math.log(spectrogram).numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pZ92HnbJGHBS"
      },
      "source": [
        "다른 스케일로의 추가 변환도 가능합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZgyedQdxGM2y"
      },
      "outputs": [],
      "source": [
        "# Convert to mel-spectrogram\n",
        "mel_spectrogram = tfio.experimental.audio.melscale(\n",
        "    spectrogram, rate=16000, mels=128, fmin=0, fmax=8000)\n",
        "\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(tf.math.log(mel_spectrogram).numpy())\n",
        "\n",
        "# Convert to db scale mel-spectrogram\n",
        "dbscale_mel_spectrogram = tfio.experimental.audio.dbscale(\n",
        "    mel_spectrogram, top_db=80)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(dbscale_mel_spectrogram.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nXd776xNIr_I"
      },
      "source": [
        "### SpecAugment\n",
        "\n",
        "위에서 언급한 데이터 준비 및 증강 API 외에도 `tensorflow-io` 패키지는 고급 스펙트럼 사진 증강을 제공하며, 특히 [SpecAugment: 자동 음성 인식을 위한 간단한 데이터 증강 방법(Park 등, 2019)](https://arxiv.org/pdf/1904.08779.pdf)에서 논의된 주파수 및 시간 마스킹이 주목할만합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dajm7k-2J5l7"
      },
      "source": [
        "#### 주파수 마스킹\n",
        "\n",
        "주파수 마스킹에서 주파수 채널 `[f0, f0 + f)`이 마스킹됩니다. 여기서 `f`는 `0`부터 주파수 마스크 매개변수 `F`까지의 균일한 분포에서 선택되고 `f0`은 `(0, ν − f)`에서 선택됩니다. 여기서 `ν`는 주파수 채널의 수입니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kLEdfkkoK27A"
      },
      "outputs": [],
      "source": [
        "# Freq masking\n",
        "freq_mask = tfio.experimental.audio.freq_mask(dbscale_mel_spectrogram, param=10)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(freq_mask.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_luycpCWLe5l"
      },
      "source": [
        "#### 시간 마스킹\n",
        "\n",
        "시간 마스킹에서 `t` 연속 시간 스텝 `[t0, t0 + t)`이 마스킹됩니다. 여기서 `t`는 `0`부터 시간 마스킹 매개변수 `T`까지의 균일한 분포에서 선택되고 `t0`는 `[0, τ − t)`에서 선택됩니다. 여기서 `τ`는 시간 스텝입니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "G1ie8J3wMMEI"
      },
      "outputs": [],
      "source": [
        "# Time masking\n",
        "time_mask = tfio.experimental.audio.time_mask(dbscale_mel_spectrogram, param=10)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(time_mask.numpy())"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "audio.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
